home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Tools / Win95 Secrets / SETUP.Z / SHOW16.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-19  |  29.7 KB  |  882 lines

  1. //==================================
  2. // SHOW16 - Matt Pietrek 1995
  3. // FILE: SHOW16.C
  4. //==================================
  5. #include <windows.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <memory.h>
  9. #include <stdarg.h>
  10. #include <toolhelp.h>
  11. #include <assert.h>
  12. #include <malloc.h>
  13. #pragma hdrstop
  14. #include "show16.h"
  15. #include "tdb.h"
  16. #include "hmodule.h"
  17.  
  18. // GetModuleName is KERNEL.27, and undocumented, so prototype it
  19. BOOL WINAPI GetModuleName(HMODULE hModule, LPSTR lpszName, UINT cb);
  20.  
  21. // Prototype the functions for this
  22. void Handle_WM_COMMAND(HWND hWndDlg, WPARAM wParam, LPARAM lParam);
  23. void Handle_WM_INITDIALOG(HWND hWndDlg);
  24. BOOL CALLBACK _export Show16DlgProc(HWND, UINT, WPARAM, LPARAM);
  25. void RecordListboxLineTypeAndValue(HWND hWnd, WORD type, WORD value);
  26. BOOL RetrieveListboxLineTypeAndValue(HWND hWnd, WORD *type, WORD *value);
  27. void UpdateTaskList(void);
  28. void UpdateModuleList(void);
  29. void ShowTaskDetails(HTASK hTask);
  30. void ShowModuleDetails(HMODULE hModule);
  31. void ShowSegmentTableDetails(HMODULE hModule);
  32. void ShowEntryTableDetails(HMODULE hModule);
  33. void ShowResourceDetails(HMODULE hModule);
  34. void ShowResidentNamesDetails(HMODULE hModule);
  35. void ShowNonResidentNamesDetails(HMODULE hModule);
  36. void lbprintf(HWND hWnd, char * format, ...);
  37. LPSTR GetResourceTypeName(WORD id);
  38. BOOL IsModule(HMODULE hModule);
  39. BOOL IsA32BitHMODULE(WORD selector);
  40. LPSTR GetTaskModuleName(HTASK hTask);
  41.  
  42. // HWNDs of the commonly used dialog controls
  43. HWND HWndMainList;
  44. HWND HWndDetails;
  45. HWND HWndDetailsDescription;
  46.  
  47.  
  48. int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance,
  49.                     LPSTR lpszCmdLine, int nCmdShow )
  50. {
  51.     DialogBox(hInstance, "Show16Dlg", 0, (DLGPROC)Show16DlgProc);
  52.     return 0;
  53. }
  54.  
  55. //
  56. // Handle the dialog's WM_COMMAND messages
  57. //
  58. void Handle_WM_COMMAND(HWND hWndDlg, WPARAM wParam, LPARAM lParam)
  59. {
  60.     //
  61.     // If user hit <enter> see which listbox has the focus, and
  62.     // change wParam and lParam to look as if the user performed
  63.     // the equivalent dbl-click action.
  64.     //
  65.     if ( wParam == IDOK )
  66.     {
  67.         HWND hWndFocus = GetFocus();
  68.         if (hWndFocus == HWndDetails )
  69.         {
  70.             wParam = IDC_LB_DETAILS; lParam = MAKELONG(0,LBN_DBLCLK);
  71.         }
  72.     }
  73.     
  74.     switch ( wParam )
  75.     {
  76.         case IDC_BUTTON_EXIT:
  77.             EndDialog(hWndDlg, 0);
  78.             break;
  79.             
  80.         case IDC_RB_TASKS:
  81.             UpdateTaskList();
  82.             // Set focus to main listbox
  83.             //SendMessage( hWndDlg, WM_NEXTDLGCTL, FALSE, 0 );
  84.             break;
  85.             
  86.         case IDC_RB_MODULES:
  87.             UpdateModuleList();
  88.             // Set focus to main listbox
  89.             //SendMessage( hWndDlg, WM_NEXTDLGCTL, FALSE, 0 );
  90.             break;
  91.             
  92.         case IDC_LB_MAIN_LIST:
  93.             if ( HIWORD(lParam) == LBN_SELCHANGE )
  94.             {
  95.                 WORD handle;
  96.                 WORD lbSelectedIndex;
  97.                 
  98.                 lbSelectedIndex =
  99.                     (WORD)SendMessage( HWndMainList, LB_GETCURSEL, 0, 0 );
  100.                 handle =
  101.                     (WORD)SendMessage(HWndMainList, LB_GETITEMDATA,
  102.                                         lbSelectedIndex, 0 );
  103.                                     
  104.                 if ( IsDlgButtonChecked(hWndDlg, IDC_RB_TASKS) )
  105.                     ShowTaskDetails( (HTASK)handle );
  106.                 else
  107.                     ShowModuleDetails( (HMODULE)handle );
  108.             }
  109.             break;
  110.             
  111.         case IDC_LB_DETAILS:
  112.             if ( HIWORD(lParam) == LBN_DBLCLK )
  113.             {
  114.                 WORD type, value;
  115.                 
  116.                 if ( !RetrieveListboxLineTypeAndValue(HWndDetails,
  117.                                                         &type, &value) )
  118.                     break;
  119.                 
  120.                 switch ( type )
  121.                 {
  122.                     case LB_ITEM_HMODULE:
  123.                         ShowModuleDetails( (HMODULE)value ); break;
  124.                     case LB_ITEM_TASK:
  125.                         ShowTaskDetails( (HTASK)value ); break;
  126.                     case LB_ITEM_SEGMENTS:
  127.                         ShowSegmentTableDetails( (HMODULE)value ); break;
  128.                     case LB_ITEM_ENTRY_TABLE:
  129.                         ShowEntryTableDetails( (HMODULE)value ); break;
  130.                     case LB_ITEM_RESOURCES:
  131.                         ShowResourceDetails( (HMODULE)value ); break;
  132.                     case LB_ITEM_RESIDENT_NAMES:
  133.                         ShowResidentNamesDetails( (HMODULE)value ); break;
  134.                     case LB_ITEM_NONRESIDENT_NAMES:
  135.                         ShowNonResidentNamesDetails( (HMODULE)value ); break;
  136.                 }
  137.             }
  138.             break;
  139.     }
  140.     return;
  141. }
  142.  
  143. void Handle_WM_INITDIALOG(HWND hWndDlg)
  144. {
  145.     HWndMainList = GetDlgItem(hWndDlg, IDC_LB_MAIN_LIST);
  146.     HWndDetails = GetDlgItem(hWndDlg, IDC_LB_DETAILS);
  147.     HWndDetailsDescription = GetDlgItem(hWndDlg, IDC_DETAILS_TYPE );
  148.     
  149.     CheckDlgButton(hWndDlg, IDC_RB_TASKS, 1);
  150.     
  151.     if ( IsDlgButtonChecked(hWndDlg, IDC_RB_TASKS) )
  152.         UpdateTaskList();   
  153. }
  154.  
  155. //
  156. // Dialog proc for the main dialog
  157. //
  158. BOOL CALLBACK _export Show16DlgProc(HWND hWndDlg, UINT msg,
  159.                                      WPARAM wParam, LPARAM lParam)
  160. {
  161.     switch ( msg )
  162.     {
  163.         case WM_COMMAND:
  164.             Handle_WM_COMMAND(hWndDlg, wParam, lParam); return TRUE;
  165.         case WM_INITDIALOG:
  166.             Handle_WM_INITDIALOG(hWndDlg); return TRUE;
  167.         case WM_CLOSE:
  168.             EndDialog(hWndDlg, 0); return FALSE;
  169.     }
  170.     return FALSE;
  171. }
  172.  
  173. void UpdateTaskList(void)
  174. {
  175.     LPTDB lpTDB = 0;
  176.     HTASK headHTask;
  177.     char szModName[10];
  178.     char szBuffer[64];
  179.     unsigned lbIndex = 0;
  180.     
  181.     SendMessage(HWndMainList, LB_RESETCONTENT, 0, 0);
  182.     
  183.     GetCurrentTask();
  184.     __asm mov [headHTask], DX
  185.  
  186.     lpTDB = MAKELP( headHTask, 0 );
  187.  
  188.     while ( lpTDB )
  189.     {
  190.         memcpy( szModName, lpTDB->TDB_ModName, 8 );
  191.         szModName[8] = 0;
  192.  
  193.         wsprintf( szBuffer, "%s %s", szModName,
  194.             lpTDB->TDB_flags & TDB_FLAGS_WIN32 ? "(Win32)" : "" );
  195.  
  196.         SendMessage( HWndMainList, LB_ADDSTRING, 0, (LPARAM)szBuffer );
  197.         SendMessage( HWndMainList, LB_SETITEMDATA,
  198.                         lbIndex, (LPARAM)SELECTOROF(lpTDB) );
  199.         lbIndex++;
  200.         
  201.         lpTDB = MAKELP( lpTDB->TDB_next, 0 );
  202.     }
  203.     
  204.     // Set selection to first task in list, and show its details
  205.     SendMessage( HWndMainList, LB_SETCURSEL, 0, 0 );
  206.     PostMessage( GetParent(HWndMainList), WM_COMMAND, IDC_LB_MAIN_LIST,
  207.                     MAKELPARAM(HWndMainList, LBN_SELCHANGE) );
  208. }
  209.  
  210. void UpdateModuleList(void)
  211. {
  212.     LPMODULE lpMODULE = 0;
  213.     HMODULE headHModule;
  214.     char szBuffer[32];
  215.     LPSTR lpszModuleName;
  216.     unsigned lbIndex = 0;
  217.     WORD selector;
  218.     
  219.     SendMessage(HWndMainList, LB_RESETCONTENT, 0, 0);
  220.  
  221.     //
  222.     // First we're going to walk the regular 16 bit module list.
  223.     //
  224.     GetModuleHandle("KERNEL");   // There will always be a "KERNEL" module
  225.     __asm mov [headHModule], DX
  226.  
  227.     lpMODULE = MAKELP( headHModule, 0 );
  228.     while ( lpMODULE )
  229.     {
  230.         lpszModuleName = MAKELP(SELECTOROF(lpMODULE),
  231.                                 lpMODULE->ne_resNamesTab );
  232.  
  233.         strncpy( szBuffer, lpszModuleName + 1, *lpszModuleName );
  234.         szBuffer[ *lpszModuleName ] = 0;
  235.         
  236.         SendMessage( HWndMainList, LB_ADDSTRING, 0, (LPARAM)szBuffer );
  237.         SendMessage( HWndMainList, LB_SETITEMDATA,
  238.                         lbIndex, (LPARAM)SELECTOROF(lpMODULE) );
  239.         lbIndex++;
  240.  
  241.         lpMODULE = MAKELP( lpMODULE->ne_npNextExe, 0 );
  242.     }
  243.  
  244.     //
  245.     // Now, let's go find the pseudo 16-bit modules created for Win32
  246.     // EXEs and DLLs.
  247.     for ( selector = 7; ; selector += 8 )
  248.     {
  249.         if ( IsA32BitHMODULE(selector) )
  250.         {
  251.             GetModuleName( selector, szBuffer, sizeof(szBuffer) );
  252.             lbprintf( HWndMainList, "%s (Win32)", szBuffer );
  253.             SendMessage( HWndMainList, LB_SETITEMDATA, lbIndex,
  254.                         (LPARAM)selector );
  255.                 lbIndex++;
  256.         }
  257.         if ( selector == 0xFFFF )
  258.             break;
  259.     }
  260.  
  261.     // Set selection to first module in list, and show its details
  262.     SendMessage( HWndMainList, LB_SETCURSEL, 0, 0 );
  263.     PostMessage( GetParent(HWndMainList), WM_COMMAND, IDC_LB_MAIN_LIST,
  264.                     MAKELPARAM(HWndMainList, LBN_SELCHANGE) );
  265. }
  266.  
  267. BYTE HookedInts[7] = {0, 2, 4, 6, 7, 0x3E, 0x75};
  268.  
  269. WORD_FLAGS ErrorModeFlags[] = 
  270. {
  271. { SEM_FAILCRITICALERRORS, "FailCriticalErrors" },
  272. { SEM_NOGPFAULTERRORBOX, "NoGPFaultErrorBox" },
  273. { SEM_NOOPENFILEERRORBOX, "NoOpenFileErrorBox" },
  274. };
  275.  
  276. void ShowTaskDetails(HTASK hTask)
  277. {
  278.     LPTDB lpTDB = MAKELP( hTask, 0 );
  279.     char szBuffer[260];
  280.     unsigned i;
  281.     
  282.     if ( !IsTask(hTask) )
  283.         return;
  284.     
  285.     wsprintf(szBuffer, "Task: %04X (%s)", hTask, GetTaskModuleName(hTask) );
  286.     SendMessage( HWndDetailsDescription, WM_SETTEXT, 0, (LPARAM)szBuffer );
  287.     SendMessage(HWndDetails, LB_RESETCONTENT, 0, 0);
  288.  
  289.     lbprintf( HWndDetails, "ModuleName: %.8s", lpTDB->TDB_ModName );
  290.         
  291.     GetModuleFileName( lpTDB->TDB_HMODULE, szBuffer, sizeof(szBuffer) );
  292.     lbprintf( HWndDetails, "+ HMODULE: %04Xh %s",
  293.                 lpTDB->TDB_HMODULE, szBuffer ); 
  294.     RecordListboxLineTypeAndValue(  HWndDetails, LB_ITEM_HMODULE,
  295.                                     lpTDB->TDB_HMODULE );
  296.     lbprintf( HWndDetails, "HINSTANCE: %04X", lpTDB->TDB_HInstance );
  297.  
  298.     lbprintf( HWndDetails, "CurrentDir: %c:%s",
  299.                 'A' + lpTDB->TDB_Drive - 0x80,
  300.                 lpTDB->TDB_current_directory );
  301.  
  302.     lbprintf( HWndDetails, "ExpWinVer: %u.%02u",
  303.             HIBYTE(lpTDB->TDB_ExpWinVer), LOBYTE(lpTDB->TDB_ExpWinVer) );
  304.  
  305.     lbprintf( HWndDetails, "PSP: %04X", lpTDB->TDB_PSP );
  306.  
  307.     lbprintf( HWndDetails, "DOS DTA: %04X:%04X",
  308.                     SELECTOROF(lpTDB->TDB_DTA),
  309.                     OFFSETOF(lpTDB->TDB_DTA) );
  310.  
  311.     lbprintf( HWndDetails, "Queue: %04X", lpTDB->TDB_Queue );
  312.     lbprintf( HWndDetails, "+ Parent: %04X %s",
  313.         lpTDB->TDB_Parent, GetTaskModuleName(lpTDB->TDB_Parent) );
  314.     RecordListboxLineTypeAndValue(  HWndDetails, LB_ITEM_TASK,
  315.                                     lpTDB->TDB_Parent );
  316.     
  317.     lbprintf( HWndDetails, "TaskFlags: %04X", lpTDB->TDB_flags );
  318.     if ( lpTDB->TDB_flags & TDB_FLAGS_WIN32 )
  319.         lbprintf( HWndDetails, "    Win32 task" );
  320.     if ( lpTDB->TDB_flags & TDB_FLAGS_WINOLDAP )
  321.         lbprintf( HWndDetails, "    Winoldap task (DOS)" );
  322.         
  323.     lbprintf( HWndDetails, "ErrMode: %04X", lpTDB->TDB_ErrMode );
  324.     for ( i=0; i < sizeof(ErrorModeFlags)/sizeof(WORD_FLAGS); i++ )
  325.         if ( ErrorModeFlags[i].value & lpTDB->TDB_ErrMode )
  326.             lbprintf( HWndDetails, "    %s", ErrorModeFlags[i].name );
  327.  
  328.     lbprintf( HWndDetails, "CompatFlags: %04X", lpTDB->TDB_CompatFlags );
  329.     lbprintf( HWndDetails, "FS Selector: %04X", lpTDB->TDB_FS_selector );
  330.     lbprintf( HWndDetails, "Ring 3 thread database: %08lX",
  331.                             lpTDB->TDB_ring3_thread_db );
  332.     lbprintf( HWndDetails, "Thunk SS: %04X", lpTDB->TDB_thunk_stack_ss );
  333.  
  334.     lbprintf( HWndDetails, "MakeProcInstance selector: %04X",
  335.                 lpTDB->TDB_MPI_Sel );
  336.                 
  337.     lbprintf( HWndDetails, "SS:SP: %04X:%04X",
  338.                 lpTDB->TDB_taskSS, lpTDB->TDB_taskSP );
  339.  
  340.     lbprintf( HWndDetails, "FP CtrlWord: %04X", lpTDB->TDB_FCW );
  341.     lbprintf( HWndDetails, "SigAction: %04X", lpTDB->TDB_SigAction );
  342.     lbprintf( HWndDetails, "USER SignalProc: %04X:%04X",
  343.                     SELECTOROF(lpTDB->TDB_USignalProc),
  344.                     OFFSETOF(lpTDB->TDB_USignalProc) );
  345.     lbprintf( HWndDetails, "GlobalNotify Proc: %04X:%04X",
  346.                     SELECTOROF(lpTDB->TDB_GNotifyProc),
  347.                     OFFSETOF(lpTDB->TDB_GNotifyProc) );
  348.                 
  349.     for ( i=0; i < 7; i++ )
  350.         lbprintf( HWndDetails, "INT %Xh handler: %04X:%04X",
  351.                     HookedInts[i],
  352.                     SELECTOROF(lpTDB->TDB_INTVECS[i]),
  353.                     OFFSETOF(lpTDB->TDB_INTVECS[i]) );
  354.  
  355.     lbprintf( HWndDetails, "Events: %u", lpTDB->TDB_nEvents );
  356.     lbprintf( HWndDetails, "Priority: %u", lpTDB->TDB_priority );
  357.  
  358.     // All these fields should be 0.  If they aren't, we want to know
  359.     // about them PRONTO!  There may be useful information in them.
  360.     assert( !lpTDB->TDB_thread_ordinal );
  361.     assert( !lpTDB->TDB_thread_next );
  362.     assert( !lpTDB->TDB_thread_tdb );
  363.     assert( !lpTDB->TDB_thread_list );
  364.     assert( !lpTDB->TDB_thread_free );
  365.     assert( !lpTDB->TDB_thread_count );
  366.     assert( !lpTDB->TDB_ASignalProc );
  367.     assert( !lpTDB->TDB_filler[0] );
  368.     assert( !lpTDB->TDB_filler[1] );
  369.     assert( !lpTDB->TDB_filler[2] );
  370.     assert( !lpTDB->TDB_Directory[0] );
  371.     assert( !lpTDB->TDB_unused1 );
  372.     assert( !lpTDB->TDB_unused2 );
  373. }
  374.  
  375. WORD_FLAGS ModuleFlags[] = 
  376. {
  377. { MODFLAGS_DLL,         "DLL" },
  378. { MODFLAGS_CALL_WEP,    "CallWep" },
  379. { 0x1000,               "0x1000" },
  380. { MODFLAGS_SELF_LOADING,"SelfLoading" },
  381. { 0x0400,               "0x0400" },
  382. { 0x0080,               "0x0080" },
  383. { 0x0040,               "ImplicitLoad" },
  384. { 0x0020,               "0x0020" },
  385. { MODFLAGS_WIN32,       "Win32" },
  386. { 0x0008,               "0x0008" },
  387. { 0x0004,               "0x0004" },
  388. { MODFLAGS_AUTODATA,    "PerProcessData" },
  389. { MODFLAGS_SINGLEDATA,  "SharedData" } 
  390. };
  391.  
  392. void ShowModuleDetails(HMODULE hModule)
  393. {
  394.     LPMODULE lpMODULE = MAKELP( hModule, 0 );
  395.     char szBuffer[260];
  396.     OFSTRUCT_EXT FAR * lpofstruct;
  397.     unsigned i;
  398.     
  399.     if ( !IsModule(hModule) )
  400.         return;
  401.  
  402.     wsprintf(szBuffer, "Module: %04X", hModule);
  403.     SendMessage( HWndDetailsDescription, WM_SETTEXT, 0, (LPARAM)szBuffer );
  404.     SendMessage(HWndDetails, LB_RESETCONTENT, 0, 0);
  405.     
  406.     lpofstruct = MAKELP( hModule, lpMODULE->ne_npFileInfo );
  407.     lbprintf( HWndDetails, "Filename: %s", lpofstruct->szPathName );
  408.     lbprintf( HWndDetails, "+ Segments: %Xh", lpMODULE->ne_cseg );
  409.     RecordListboxLineTypeAndValue(  HWndDetails, LB_ITEM_SEGMENTS, hModule );
  410.  
  411.     lbprintf(HWndDetails, "+ Resources: %04Xh", lpMODULE->ne_rsrcTab);
  412.     RecordListboxLineTypeAndValue( HWndDetails, LB_ITEM_RESOURCES, hModule );
  413.  
  414.     lbprintf(HWndDetails, "+ ResidentNames: %04Xh", lpMODULE->ne_resNamesTab);
  415.     RecordListboxLineTypeAndValue(HWndDetails, LB_ITEM_RESIDENT_NAMES,
  416.                                     hModule );
  417.  
  418.     lbprintf(HWndDetails, "+ Non-ResidentNames Offs: %lXh  size: %04X",
  419.             lpMODULE->ne_nonResNamesTab, lpMODULE->ne_cbNonResNamesTab );
  420.     RecordListboxLineTypeAndValue(HWndDetails, LB_ITEM_NONRESIDENT_NAMES,
  421.                                     hModule );
  422.  
  423.     lbprintf( HWndDetails, "+ EntryTableOffs: %04Xh",
  424.                 lpMODULE->ne_npEntryTable );
  425.     RecordListboxLineTypeAndValue(HWndDetails, LB_ITEM_ENTRY_TABLE, hModule );
  426.  
  427.     lbprintf( HWndDetails, "Usage: %Xh", lpMODULE->ne_usage );
  428.     lbprintf( HWndDetails, "Flags: %02Xh", lpMODULE->ne_flags );
  429.     for ( i=0; i < sizeof(ModuleFlags)/sizeof(WORD_FLAGS); i++ )
  430.         if ( ModuleFlags[i].value & lpMODULE->ne_flags )
  431.             lbprintf( HWndDetails, "    %s", ModuleFlags[i].name );
  432.         
  433.     lbprintf( HWndDetails, "ExpWinVer: %u.%02u",
  434.             HIBYTE(lpMODULE->ne_expver), LOBYTE(lpMODULE->ne_expver) );
  435.     lbprintf( HWndDetails, "DGROUP index: %Xh", lpMODULE->ne_autodata );
  436.     lbprintf( HWndDetails, "Local heap size: %Xh bytes", lpMODULE->ne_heap );
  437.     lbprintf( HWndDetails, "Stack size: %Xh bytes", lpMODULE->ne_stack );
  438.     lbprintf( HWndDetails, "Entry point: %04X:%04X",
  439.                     SELECTOROF(lpMODULE->ne_csip),
  440.                     OFFSETOF(lpMODULE->ne_csip) );
  441.     lbprintf( HWndDetails, "Initial SS:SP: %04X:%04X",
  442.                     SELECTOROF(lpMODULE->ne_sssp),
  443.                     OFFSETOF(lpMODULE->ne_sssp) );
  444.                 
  445.     if ( lpMODULE->ne_cModules )
  446.     {
  447.         LPWORD lpModuleList = MAKELP(hModule, lpMODULE->ne_modRefTab);
  448.         
  449.         lbprintf( HWndDetails, "imported modules:");
  450.         for ( i=0; i <  lpMODULE->ne_cModules; i++ )
  451.         {
  452.             GetModuleName( lpModuleList[i], szBuffer, sizeof(szBuffer) );
  453.             lbprintf( HWndDetails, "    + %s", szBuffer );
  454.             RecordListboxLineTypeAndValue(  HWndDetails, LB_ITEM_HMODULE,
  455.                                             lpModuleList[i] );
  456.         }
  457.     }
  458.     
  459.     // The fields in this "if" statement are only present for the
  460.     // pseudo Win32 modules
  461.     if ( lpMODULE->ne_flags & MODFLAGS_WIN32 )
  462.     {
  463.         lbprintf( HWndDetails, "Win32 Base Addr: %08lX",
  464.                     lpMODULE->ne_Win32BaseAddr1 );
  465.         assert ( lpMODULE->ne_Win32BaseAddr1 == lpMODULE->ne_Win32BaseAddr2 );
  466.  
  467.         lbprintf( HWndDetails, "Win32 Resource Addr: %08lX",
  468.                     lpMODULE->ne_Win32ResourceAddr );       
  469.     }
  470.     
  471.     lbprintf( HWndDetails, "alignment: %u bytes", 1 << lpMODULE->ne_align );
  472.     lbprintf( HWndDetails, "OtherFlags: %02X", lpMODULE->ne_flagsother );
  473.     lbprintf( HWndDetails, "ImportedNames2: %04X",
  474.             lpMODULE->ne_importedNamesTab2 );
  475.     lbprintf( HWndDetails, "ImportedNames3: %04X",
  476.             lpMODULE->ne_importedNamesTab3 );
  477.  
  478.     lbprintf( HWndDetails, "SwapArea: %lXh bytes",
  479.                 lpMODULE->ne_swaparea * 16L );
  480.             
  481.     // These fields should be 0.  If they aren't, we want to know
  482.     // about them PRONTO!  There may be useful information in them.
  483.     assert ( !lpMODULE->ne_cres );
  484. }
  485.  
  486. void ShowSegmentTableDetails(HMODULE hModule)
  487. {
  488.     LPMODULE lpMODULE = MAKELP( hModule, 0 );
  489.     LPSEGMENT_RECORD pSeg;
  490.     char szBuffer[260];
  491.     char szModuleName[32];
  492.     unsigned i;
  493.     
  494.     if ( !IsModule(hModule) )
  495.         return;
  496.  
  497.     if ( lpMODULE->ne_cseg == 0 )   // Make sure there's something to see...
  498.         return;
  499.     
  500.     GetModuleName( hModule, szModuleName, sizeof(szModuleName) );
  501.     wsprintf(szBuffer, "Segments for module %04X (%s)",
  502.                 hModule, szModuleName);
  503.     SendMessage( HWndDetailsDescription, WM_SETTEXT, 0, (LPARAM)szBuffer );
  504.     SendMessage(HWndDetails, LB_RESETCONTENT, 0, 0);
  505.  
  506.     // The array of segment records starts right after the 40h NE header.
  507.     pSeg = (LPSEGMENT_RECORD)MAKELP( hModule, lpMODULE->ne_segtab );
  508.     
  509.     lbprintf( HWndDetails, "SEG HNDL TYPE SIZE" );
  510.         
  511.     for ( i=0; i < lpMODULE->ne_cseg; i++ )
  512.     {
  513.         lbprintf( HWndDetails, "%02X:   %04X %s %04X bytes",
  514.             i+1, pSeg->handle, pSeg->flags & 1 ? "DATA" : "CODE",
  515.             pSeg->alloc_size );
  516.         pSeg++;
  517.     }
  518. }
  519.  
  520. void ShowEntryTableDetails(HMODULE hModule)
  521. {
  522.     LPMODULE lpMODULE = MAKELP( hModule, 0 );
  523.     LPENTRY_BUNDLE_HEADER lpBundleHdr;
  524.     LPENTRY lpEntry;
  525.     char szBuffer[260];
  526.     char szModuleName[32];
  527.     unsigned i;
  528.     
  529.     if ( !IsModule(hModule) )
  530.         return;
  531.  
  532.     if ( lpMODULE->ne_npEntryTable == 0 )
  533.         return;
  534.  
  535.     lpBundleHdr = MAKELP( hModule, lpMODULE->ne_npEntryTable );
  536.     
  537.     // Are there any entries to show???
  538.     if ( lpBundleHdr->lastEntry == lpBundleHdr->firstEntry )
  539.         return;
  540.     
  541.     GetModuleName( hModule, szModuleName, sizeof(szModuleName) );
  542.     wsprintf(szBuffer, "Entry table for module %04X (%s)",
  543.                 hModule, szModuleName);
  544.     SendMessage( HWndDetailsDescription, WM_SETTEXT, 0, (LPARAM)szBuffer );
  545.     SendMessage(HWndDetails, LB_RESETCONTENT, 0, 0);
  546.     
  547.     while ( TRUE )
  548.     {
  549.         unsigned cEntries = lpBundleHdr->lastEntry - lpBundleHdr->firstEntry;
  550.  
  551.         lpEntry = (LPENTRY)(lpBundleHdr+1); // Entries start after bundle hdr
  552.         
  553.         for ( i=0; i < cEntries; i++ )
  554.         {
  555.             lbprintf( HWndDetails, "%3u: %02X:%04X  %s %s",
  556.                         lpBundleHdr->firstEntry + 1 + i,
  557.                         lpEntry->segNumber, lpEntry->offset,
  558.                         lpEntry->segType == 0xFF ? "MOVEABLE" : "FIXED",
  559.                         lpEntry->flags & 1 ? "EXPORTED" : "" );
  560.  
  561.             lpEntry++;
  562.         }
  563.  
  564.         if ( lpBundleHdr->nextBundle == 0 )
  565.             break;      
  566.         lpBundleHdr = MAKELP( hModule, lpBundleHdr->nextBundle );
  567.     }
  568. }
  569.  
  570. void ShowResourceDetails(HMODULE hModule)
  571. {
  572.     LPMODULE lpMODULE = MAKELP( hModule, 0 );
  573.     LPRESOURCE_TYPE lpRsrcType, lpRsrcEnd;
  574.     LPRESOURCE_INFO lpRsrcInfo;
  575.     LPBYTE lpName;
  576.     char szBuffer[260];
  577.     char szModuleName[32];
  578.     unsigned i;
  579.     
  580.     if ( !IsModule(hModule) )
  581.         return;
  582.  
  583.     if ( lpMODULE->ne_rsrcTab == lpMODULE->ne_resNamesTab )
  584.         return;
  585.  
  586.     GetModuleName( hModule, szModuleName, sizeof(szModuleName) );
  587.     wsprintf(szBuffer, "Resources for module %04X (%s)",
  588.                 hModule, szModuleName);
  589.     SendMessage( HWndDetailsDescription, WM_SETTEXT, 0, (LPARAM)szBuffer );
  590.     SendMessage(HWndDetails, LB_RESETCONTENT, 0, 0);
  591.     
  592.     // Get a pointer to the first resource type header.  The "+2" skips
  593.     // past the alignment WORD at the beginning
  594.     lpRsrcType = MAKELP( hModule, lpMODULE->ne_rsrcTab + 2);
  595.     lpRsrcEnd = MAKELP( hModule, lpMODULE->ne_resNamesTab );
  596.     
  597.     while ( lpRsrcType < lpRsrcEnd )
  598.     {
  599.         if ( lpRsrcType->ID == 0 )
  600.             break;
  601.  
  602.         if ( lpRsrcType->ID & 0x8000 )      // A predefined standard resource
  603.         {
  604.             lbprintf( HWndDetails, "%s - Handler: %04X:%04X",
  605.                         GetResourceTypeName( lpRsrcType->ID ),
  606.                         HIWORD(lpRsrcType->function),
  607.                         LOWORD(lpRsrcType->function) );
  608.         }
  609.         else    // A named resource
  610.         {
  611.             lpName = MAKELP(hModule, lpMODULE->ne_rsrcTab + lpRsrcType->ID );
  612.             memcpy( szBuffer, lpName+1, *lpName );
  613.             szBuffer[*lpName] = 0;
  614.             lbprintf( HWndDetails, "NamedResource %s - Handler: %04X:%04X",
  615.                         szBuffer,
  616.                         HIWORD(lpRsrcType->function),
  617.                         LOWORD(lpRsrcType->function) );
  618.         }
  619.         
  620.         lpRsrcInfo = (LPRESOURCE_INFO)(lpRsrcType+1);
  621.  
  622.         for ( i = 0; i < lpRsrcType->count; i++ )
  623.         {
  624.             // If it's a named resource, so retrieve the string.  The
  625.             // ID value is an offset within the resource table.
  626.             if ( !(lpRsrcInfo->ID & 0x8000) )
  627.             {
  628.                 lpName = MAKELP(hModule, lpMODULE->ne_rsrcTab
  629.                                         + lpRsrcInfo->ID );
  630.                 memcpy( szBuffer, lpName+1, *lpName );
  631.                 szBuffer[*lpName] = 0;
  632.             }
  633.             else    // An integer ID resource
  634.                 wsprintf(szBuffer, "%u", lpRsrcInfo->ID);
  635.             
  636.             lbprintf( HWndDetails,
  637.                 "  offs: %04X  len: %04Xh  ID: %s  hndl: %04X",
  638.                 lpRsrcInfo->offset, lpRsrcInfo->length,
  639.                 szBuffer, lpRsrcInfo->handle );
  640.  
  641.             lpRsrcInfo++;   // Point at next resource of this type
  642.         }
  643.         
  644.         lpRsrcType = (LPRESOURCE_TYPE)  // Point at next resource type
  645.                     ((LPBYTE)lpRsrcType + sizeof(RESOURCE_TYPE)
  646.                     + (lpRsrcType->count * sizeof(RESOURCE_INFO)));
  647.     }
  648. }
  649.  
  650. void ShowResidentNamesDetails(HMODULE hModule)
  651. {
  652.     LPMODULE lpMODULE = MAKELP( hModule, 0 );
  653.     LPBYTE lpNameEntry;
  654.     char szBuffer[260];
  655.     char szModuleName[32];
  656.  
  657.     if ( !IsModule(hModule) )
  658.         return;
  659.  
  660.     GetModuleName( hModule, szModuleName, sizeof(szModuleName) );
  661.     wsprintf(szBuffer, "Resident names for module %04X (%s)",
  662.                 hModule, szModuleName);
  663.     SendMessage( HWndDetailsDescription, WM_SETTEXT, 0, (LPARAM)szBuffer );
  664.     SendMessage(HWndDetails, LB_RESETCONTENT, 0, 0);
  665.     
  666.     lpNameEntry = MAKELP( hModule, lpMODULE->ne_resNamesTab );
  667.  
  668.     //  Each entry is as follows:
  669.     //  BYTE    - length of string that follows
  670.     //  char[?] - the name.  Size is given by previous field
  671.     //  WORD    - the export ordinal for this function
  672.     
  673.     while ( TRUE )
  674.     {
  675.         if ( *lpNameEntry == 0 )    // A 0-length terminates the table
  676.             break;
  677.  
  678.         memcpy(szBuffer, lpNameEntry+1, *lpNameEntry);
  679.         szBuffer[ *lpNameEntry ] = 0;
  680.         lbprintf( HWndDetails, "%03u %s",
  681.                     *(LPWORD)(lpNameEntry + *lpNameEntry + 1), szBuffer );
  682.         lpNameEntry += (*lpNameEntry + 3);
  683.     }
  684. }
  685.  
  686. void ShowNonResidentNamesDetails(HMODULE hModule)
  687. {
  688.     LPMODULE lpMODULE = MAKELP( hModule, 0 );
  689.     LPBYTE lpNameEntry, lpNRNTable;
  690.     char szBuffer[260];
  691.     char szModuleName[32];
  692.     HFILE hFile = HFILE_ERROR;
  693.     
  694.     if ( !IsModule(hModule) )
  695.         return;
  696.  
  697.     // Open up the file, seek to the non-resident names, allocate
  698.     // memory for the buffer, and read the table in.  Does error checking.
  699.     if ( !GetModuleFileName(hModule, szBuffer, sizeof(szBuffer)) )
  700.         return;
  701.     hFile = _lopen( szBuffer, READ );
  702.     if ( HFILE_ERROR == hFile )
  703.         return;
  704.     if ( HFILE_ERROR==_llseek(hFile, lpMODULE->ne_nonResNamesTab, SEEK_SET))
  705.         goto done;
  706.     lpNRNTable = malloc( lpMODULE->ne_cbNonResNamesTab );
  707.     if ( !lpNRNTable )
  708.         goto done;
  709.     if ( _lread(hFile, lpNRNTable, lpMODULE->ne_cbNonResNamesTab)
  710.             != lpMODULE->ne_cbNonResNamesTab )
  711.         goto done;
  712.  
  713.     lpNameEntry = lpNRNTable;
  714.     
  715.     GetModuleName( hModule, szModuleName, sizeof(szModuleName) );
  716.     wsprintf(szBuffer, "Non-resident names for module %04X (%s)",
  717.                 hModule, szModuleName);
  718.     SendMessage( HWndDetailsDescription, WM_SETTEXT, 0, (LPARAM)szBuffer );
  719.     SendMessage(HWndDetails, LB_RESETCONTENT, 0, 0);
  720.     
  721.     //  Each entry has the same format as the resident names table
  722.  
  723.     while ( TRUE )
  724.     {
  725.         if ( *lpNameEntry == 0 )    // A 0-length terminates the table
  726.             break;
  727.  
  728.         memcpy(szBuffer, lpNameEntry+1, *lpNameEntry);
  729.         szBuffer[ *lpNameEntry ] = 0;
  730.         lbprintf( HWndDetails, "%03u %s",
  731.                     *(LPWORD)(lpNameEntry + *lpNameEntry + 1), szBuffer );
  732.         lpNameEntry += (*lpNameEntry + 3);
  733.     }
  734.     
  735. done:
  736.     // Clean up things we created
  737.     if ( HFILE_ERROR != hFile )
  738.         _lclose( hFile );
  739.     if ( lpNRNTable )
  740.         free( lpNRNTable );
  741. }
  742.  
  743. void lbprintf(HWND hWnd, char * format, ...)
  744. {
  745.     char szBuffer[512];
  746.     va_list argptr;
  747.           
  748.     va_start(argptr, format);
  749.     vsprintf(szBuffer, format, argptr);
  750.     va_end(argptr);
  751.  
  752.     SendMessage( hWnd, LB_ADDSTRING, 0, (LPARAM)szBuffer );
  753. }
  754.  
  755. // Records the type (module, task, etc...) of the line that was just
  756. // added to the specified listbox window, along with the value.
  757. void RecordListboxLineTypeAndValue(HWND hWnd, WORD type, WORD value)
  758. {
  759.     unsigned lastIndex = (WORD)SendMessage( hWnd, LB_GETCOUNT, 0, 0 );
  760.     if ( !lastIndex )
  761.         return;
  762.     
  763.     lastIndex--;    // Index is 0 based
  764.         
  765.     SendMessage( hWnd, LB_SETITEMDATA, lastIndex, MAKELONG(value, type) );
  766. }
  767.  
  768. BOOL RetrieveListboxLineTypeAndValue(HWND hWnd, WORD *type, WORD *value)
  769. {
  770.     DWORD itemData;
  771.     unsigned index = (WORD)SendMessage( hWnd, LB_GETCURSEL, 0, 0 );
  772.  
  773.     itemData = SendMessage( hWnd, LB_GETITEMDATA, index, 0 );
  774.     if ( !itemData && itemData == (DWORD)LB_ERR )
  775.         return FALSE;
  776.  
  777.     *type = HIWORD( itemData );
  778.     *value = LOWORD( itemData );
  779.     
  780.     return TRUE;
  781. }
  782.  
  783. char *ResourceTypes[] =
  784. {
  785.     "",
  786.     "Cursor",           // 1
  787.     "Bitmap",           // 2
  788.     "Icon",             // 3
  789.     "Menu",             // 4
  790.     "Dialog",           // 5
  791.     "String Table",     // 6
  792.     "Font Directory",   // 7
  793.     "Font",             // 8
  794.     "Accelerator",      // 9
  795.     "RC Data",          //10
  796.     "Error Table",      //11
  797.     "Group Cursor",     //12
  798.     "Unknown",          //13
  799.     "Group Icon",       //14
  800.     "Name Table",       //15
  801.     "Version info"      //16
  802. };
  803.  
  804. LPSTR GetResourceTypeName(WORD id)
  805. {
  806.     static char szBuffer[64];
  807.     
  808.     if ( (id & 0x8000) == 0 )
  809.         return "NamedResource";
  810.     
  811.     id &= 0x7FFF;   // Turn off high bit
  812.     
  813.     if ( (id >= 1) && (id <= 16) )
  814.         return ResourceTypes[id];
  815.     
  816.     if ( id == 0xCC )
  817.         return "TrueType Font";
  818.     
  819.     wsprintf( szBuffer, "Unknown_%u", id );
  820.     return szBuffer;
  821. }
  822.  
  823. BOOL IsModule(HMODULE hModule)
  824. {
  825.     LPMODULE lpMODULE = MAKELP( hModule, 0 );
  826.     
  827.     if ( IsBadReadPtr( lpMODULE, 2) )
  828.         return FALSE;
  829.     
  830.     return lpMODULE->ne_signature == 0x454E;    // Is 'NE' signature there?
  831. }
  832.  
  833. BOOL IsA32BitHMODULE(WORD selector)
  834. {
  835.     LPMODULE lpMODULE;
  836.  
  837.     __asm {
  838.         lar     AX, [selector]
  839.         jc      false
  840.         cmp     ah, 0F3h // Present, ring 3, writeable, accessed data segment
  841.         jne     false;
  842.     }
  843.     
  844.     lpMODULE = MAKELP( selector, 0 );
  845.     if ( IsBadReadPtr(lpMODULE, sizeof(MODULE)) )   // Is the seg big enough?
  846.         return FALSE;
  847.  
  848.     if ( lpMODULE->ne_signature != 0x454E ) // look for NE signature
  849.         return FALSE;
  850.  
  851.     if ( GetSelectorBase(selector) < 0x80000000LU ) // IMTE is in system
  852.         return FALSE;                               // memory > 2GB
  853.  
  854.     if ( lpMODULE->ne_align != 0 )          // alignment is always 1 in 32 bit
  855.         return FALSE;                       // modules
  856.  
  857.     if ( lpMODULE->ne_cseg != 0 )           // No segments in 32 bit modules
  858.         return FALSE;
  859.  
  860.     if ( lpMODULE->ne_usage != 1 )  // Usage will always be 1
  861.         return TRUE;
  862.     
  863.     if ( lpMODULE->ne_flags == 0x8010 ) // Are DLL and Win32 flags set?
  864.         return TRUE;
  865.  
  866. false:
  867.     return FALSE;
  868. }
  869.  
  870. LPSTR GetTaskModuleName(HTASK hTask)
  871. {
  872.     LPTDB lpTDB = MAKELP( hTask, 0 );
  873.     static char szBuffer[10];
  874.     
  875.     if ( !IsTask(hTask) )
  876.         return "<unknown TDB>";
  877.     memcpy( szBuffer, lpTDB->TDB_ModName, 8 );
  878.     szBuffer[8] = 0;
  879.     return szBuffer;
  880. }
  881.  
  882.